/*
 */
package org.vectrics.mail;

import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import org.apache.log4j.Logger;
import org.vectrics.SystemException;
import org.vectrics.config.MailConfiguration;
import org.vectrics.hibernate.ThreadProperties;
import org.vectrics.user.ContactInfo;
import org.vectrics.user.Person;



/**
 * @author mmoore
 */
public class UserMailThread extends Thread {
    private transient final Logger log = Logger.getLogger(UserMailThread.class);
    private Collection persons = null;
    private boolean isHtml = false;
    private MailMessage mailMessage = null;
    private Session session = null;
    private MailConfiguration mailConfig = null;
    private Class callingClass = null;
    
    public UserMailThread(Class callingClass, MailConfiguration mailConfig, 
    			Collection persons, MailMessage mailMessage) {
		if (mailMessage.getSubject() == null)
			throw new SystemException("Email subject is null");
		this.callingClass = callingClass;
        this.setPriority(Thread.MIN_PRIORITY);
        this.isHtml = (mailMessage.getContentType() == MailMessage.CONTENT_HTML);
        this.persons = persons;
        this.mailMessage = mailMessage;
        this.mailConfig = mailConfig;
        
		session = mailConfig.getMailSession();
    }
		
    
    public void run() {
        try {
        	Iterator iter = persons.iterator();
	   		while (iter.hasNext()) {
	   			Person person = (Person)iter.next();
	   			
	       		MimeMessage message = null;
	       		if (isHtml) {
					message = this.createHtmlMessage(mailMessage);
	       		} else {
					message = this.createTextMessage(mailMessage);
	       		}
	       		
	       		if (message == null) {
	       		    throw new SystemException("MimeMessage not created, html = " + isHtml);
	       		}
	       		
	            InternetAddress fromAddr = null;
	            try {
	                fromAddr = new InternetAddress(mailMessage.getFromAddress(), mailMessage.getFromName());
	                message.setFrom(fromAddr);
	            } catch (Exception me) {
	                throw new SystemException("Exception making from address: " + mailMessage.getFromAddress() 
	                        + "  From name = " + mailMessage.getFromName(), me);
	            }
	
	            ContactInfo contactInfo = person.getContactInfo();
	            if (contactInfo != null) {
	            	
	            	if ((contactInfo.getEmail() != null)
	            		&& (contactInfo.getEmail().trim().length() > 0)
						&& (contactInfo.getEmail().indexOf("@") > 0) 
						) {
		            	if (log.isDebugEnabled()) {
		            		log.debug("sendMessage() - subject = " + mailMessage.getSubject());
		            		log.debug("sendMessage() - recipient = " + person.getName());
		            		log.debug("sendMessage() - recipient e-mail = " 
		            				+ person.getContactInfo().getEmail());
		            		log.debug("sendMessage() - from = " + mailMessage.getFromName());
		            		log.debug("sendMessage() - e-mail - from = " + mailMessage.getFromAddress());
		            	}
		            	if (contactInfo.getEmail().indexOf("testemail") > 0) {
		            		if (log.isDebugEnabled())
		            			log.debug("Test email address found, email not sent." +
		            				"\r\n - To Email: " + contactInfo.getEmail() +
		            				"\r\n - Subject:  " + mailMessage.getSubject()
		            				);
		            	} else {
			                log.debug("sendMessage() - creating MimeMessage");
			                log.debug("sendMessage() - setting from");
			    
			                log.debug("sendMessage() - setting to");
			                InternetAddress toAddr = null;
			                try {
		                       toAddr = new InternetAddress(contactInfo.getEmail().trim(), 
		                        		person.getName());
			                } catch (UnsupportedEncodingException ue) {
			                    
			                }
		
			                try {
			                	if (log.isDebugEnabled())
			                		log.debug("Adding email recipient: " + toAddr.getAddress());
			                    message.addRecipient(Message.RecipientType.TO, toAddr);
			                } catch (MessagingException me) {
			                    throw new SystemException("Messaging excpetion adding recipient: " 
			                    		+ toAddr + "  Subject =" + mailMessage.getSubject(), 
			                            me);
			                }
			                
			       			try {
			       				Transport.send(message);
			       				if (log.isDebugEnabled())
			       					log.debug("Finished sending email without error to: " + contactInfo.getEmail());
			       			} catch (MessagingException me) {
			       				log.error("MessagingException sending email" +
									"\r\n - Calling class: " + this.callingClass.getName() +
									"\r\n - Host:          " + session.getProperty("mail.host") +
									"\r\n - Pwd:           " + session.getProperty("mail.password") +
									"\r\n - User:          " + session.getProperty("mail.user") +
									"\r\n - SMTP User:     " + session.getProperty("mail.smtp.user") +
									"\r\n - SMTP PWD:      " + session.getProperty("mail.smtp.password")
			       						, me);
			       				String recipientList = "";
			       				try {
				       				Address[] recipients = message.getAllRecipients();
				       				for (int i = 0; i < recipients.length; i++) {
				       					InternetAddress address = (InternetAddress)recipients[i];
				       					recipientList += address.getAddress();
				       					if (i < recipients.length - 1) {
				       						recipientList += "; ";       					}
				       				}
			       				} catch (Exception ex) {
			       				    log.error("Exception showing recipient list, subject = " 
											+ "\r\n - Calling class: " + this.callingClass.getName() 
			       				            + "\r\n - Subject:       " + mailMessage.getSubject()
			       				            , ex);
			       				}
			       				log.error("Exception sending e-mail to recipients,\r\n - Subject = " 
 										+ "\r\n - Calling class: " + this.callingClass.getName() 
			       				            + "\r\n - Subject:    " +  mailMessage.getSubject()
			       						+ "\r\nRecipients: " + recipientList, me);
			       			} catch (Exception ex) {
			       				log.error("Exception sending email" +
 									    "\r\n - Calling class: " + this.callingClass.getName() +  
			       						"\r\n - Host: " + this.mailConfig.getMailHost() +
			       						"\r\n - User: " + this.mailConfig.getMailUserName() +
			       						"\r\n - Pwd:  " + this.mailConfig.getMailPassword()
			       						, ex);
			       			} finally {
			       				ThreadProperties.forcedCommitAndClose();
			       			}
		            	}
	            	} else {
		                log.debug("sendMessage() - user does not have valid e-mail address - " 
		                        + person.getName() 
		                		+ "  E-mail = " + person.getContactInfo().getEmail());
	            	}
	            }
	            else {
	                log.debug("sendMessage() - user does not have contact info - " 
	                		+ person.getName());
	            }
	   		}
        } catch(Throwable ex) {
            log.error("Exception sending e-mail" 
						+ "\r\n - Calling class: " + this.callingClass.getName() 
            		, ex);
        }
    }
    
    /*
     * 
     */
    public MimeMessage createTextMessage(MailMessage mailMessage) throws MailException {
        MimeMessage msg = null;
        log.debug("createTextMessage() called.");
        if (mailMessage.getSubject() == null) {
            log.error("Subject was null in createTextMessage() - body = " + mailMessage.getBody());
        } else {
	        try {
	            msg = new MimeMessage(session);
	            msg.setSubject(mailMessage.getSubject());
	            msg.setSentDate(new Date());
	        	if (mailMessage.getAttachedFiles().size() == 0) {
		            msg.setContent(mailMessage.getBody(), "text/plain");
	        	} else {
		            Multipart multipart = new MimeMultipart();
		            
		            Iterator iter = mailMessage.getAttachedFiles().iterator();
		            while (iter.hasNext()) {
		            	String attachedFileName = (String)iter.next();
			            MimeBodyPart messageBodyPart = new MimeBodyPart();
			            DataSource source = 
			              new FileDataSource(attachedFileName);
			            messageBodyPart.setDataHandler(
			              new DataHandler(source));
			            messageBodyPart.setFileName(attachedFileName);
			            multipart.addBodyPart(messageBodyPart);
		            }
		            
		            MimeBodyPart messageBodyPart = new MimeBodyPart();
		            messageBodyPart.setText(mailMessage.getBody());
	                multipart.addBodyPart(messageBodyPart);

		            
		            msg.setContent(multipart);
	        	}

	            
	        }
	        catch (javax.mail.MessagingException me) {
	            msg = null;
	            log.error("Exception creating MIME message." 
							+ "\r\n - Calling class: " + this.callingClass.getName() 
	            		, me);
	            throw new MailException("Exception creating MIME message.", me);
	        }
        }
        return(msg);
    }

    /*
     * 
     */
    public MimeMessage createHtmlMessage(MailMessage mailMessage) throws MailException {
        log.debug("createHtmlMessage() called.");
        MimeMessage msg = null;
        if (mailMessage.getSubject() == null) {
               throw new MissingSubjectMailException("Subject missing from message.");
        }
        
        try {
            msg = new MimeMessage(session);
            msg.setSubject(mailMessage.getSubject());
            msg.setContent(mailMessage.getBody(), "text/html");
            msg.setSentDate(new Date());
            log.debug("createHtmlMessage() - content type = " + msg.getContentType());
        }
        catch (javax.mail.MessagingException me) {
            msg = null;
            log.error("Exception creating MIME message." 
						+ "\r\n - Calling class: " + this.callingClass.getName() 
            		, me);
            throw new MailException("Exception creating MIME message.", me);
        }
        return(msg);
    }
    
    
}
